りおんクロニクル


SQLite × ロック対策|database is locked の根本解決【2026年版】

Home【2026年版】C# / .NET入門と実践ガイド|基礎・業務アプリ開発・SQLite連携まで体系的に解説

SQLiteで最も多いトラブルが database is locked。 特に C#(Microsoft.Data.Sqlite)で業務アプリを作ると、 同時書き込み・reader閉じ忘れ・長時間トランザクション が原因で頻発します。

この記事でわかること
・database is locked の根本原因
・同時書き込みを防ぐ設計
・WALモードの有効化
・トランザクションの正しい使い方
・非同期処理との組み合わせ方
・業務アプリ向けベストプラクティス

1. database is locked の根本原因

SQLiteは「単一ファイルDB」のため、次の状況でロックが発生します。

重要: SQLiteは「同時書き込みが1つしかできない」構造です。 これを理解して設計しないとロック地獄になります。

2. 最重要:書き込みは“直列化”する(同時に1つだけ)

SQLiteは同時書き込みに弱いため、 書き込み処理は必ず1つずつ順番に実行する必要があります。

■ C#での直列化(lock構文)

private static readonly object _writeLock = new();

public void SaveUser(User user)
{
    lock (_writeLock)
    {
        using var con = new SqliteConnection(_cs);
        con.Open();

        var sql = "UPDATE Users SET Name=@name WHERE Id=@id";
        using var cmd = new SqliteCommand(sql, con);
        cmd.Parameters.AddWithValue("@name", user.Name);
        cmd.Parameters.AddWithValue("@id", user.Id);

        cmd.ExecuteNonQuery();
    }
}

ポイント

3. reader を必ず閉じる(using必須)

reader を閉じ忘れると、SQLiteは「読み込み中」と判断し、 書き込みがブロックされて locked が発生します。

■ NG例(reader閉じ忘れ)

var reader = cmd.ExecuteReader();
// reader.Close() を忘れる → locked地獄

■ OK例(usingで自動解放)

using var reader = cmd.ExecuteReader();

4. トランザクションは“短く”まとめる

トランザクション中は書き込みロックが保持されるため、 長時間のトランザクションは絶対にNG

■ 正しいパターン

using var tran = con.BeginTransaction();

try
{
    // INSERT/UPDATE をまとめて実行
    tran.Commit();
}
catch
{
    tran.Rollback();
}

ポイント

5. WALモードを有効化する(読み書き並列に強くなる)

SQLiteはデフォルトでは「ロックしやすい」 → WAL(Write-Ahead Logging)モードにすると改善します。

■ WALモードを有効化

using var con = new SqliteConnection(_cs);
con.Open();

using var cmd = new SqliteCommand("PRAGMA journal_mode=WAL;", con);
cmd.ExecuteNonQuery();

WALのメリット

注意: WALモードはネットワークドライブでは非推奨。 ローカルDBで使うのが基本。

6. 非同期処理(async/await)でUIフリーズを防ぐ

UIスレッドでDBアクセスすると、 処理が詰まってロックが発生しやすくなります。

■ 非同期で書き込み

await cmd.ExecuteNonQueryAsync();

■ DataTable.Load は同期 → Task.Run で逃がす

await Task.Run(() =>
{
    dt.Load(reader);
});

7. バックアップ中のロック対策

ファイルコピー中に書き込みが走ると locked が発生します。

■ 最も安全:オンラインバックアップAPI

source.BackupDatabase(destination);

■ NG:書き込み中に File.Copy

これは高確率で locked を引き起こします。

8. database is locked を根本から防ぐ設計まとめ

まとめ:SQLiteのロックは“設計で防ぐ”のが最も効果的

database is locked は「SQLiteの欠点」ではなく「設計の問題」です。 この記事の対策を組み合わせれば、ロック地獄から完全に抜け出せます。

前のページ  次のページ